package cn.yiufung.qxquartz.utils;

import cn.yiufung.qxquartz.common.ScheduleConstants;
import cn.yiufung.qxquartz.entity.SystemScheduledDO;
import cn.yiufung.qxquartz.entity.SystemScheduledLogDO;
import cn.yiufung.qxquartz.service.SystemScheduledLogService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 抽象定时任务job
 * @author 姚锋
 * @createTime 2023年08月18日 15:02:00
 */
public abstract class AbstractQuartzJob implements Job {

    private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        SystemScheduledDO systemScheduledDO = (SystemScheduledDO) jobExecutionContext.getMergedJobDataMap().get(ScheduleConstants.SCHEDULED_DO);
        LocalDateTime start = LocalDateTime.now();
        try {
            doExecute(jobExecutionContext,
                    systemScheduledDO);
            saveLog(systemScheduledDO, null, start);
        }catch (Exception e){
            log.error("执行定时任务异常", e);
            saveLog(systemScheduledDO, e, start);
        }
    }

    protected void saveLog(SystemScheduledDO systemScheduledDO, Exception e, LocalDateTime start){
        SystemScheduledLogDO systemScheduledLogDO = new SystemScheduledLogDO();
        systemScheduledLogDO.setScheduledId(systemScheduledDO.getId());
        systemScheduledLogDO.setJobName(systemScheduledDO.getJobName());
        systemScheduledLogDO.setJobGroup(systemScheduledDO.getJobGroup());
        systemScheduledLogDO.setInvokeTarget(systemScheduledDO.getInvokeTarget());
        systemScheduledLogDO.setCronExpression(systemScheduledDO.getCronExpression());
        systemScheduledLogDO.setMisfirePolicy(systemScheduledDO.getMisfirePolicy());
        //显示异常信息
        if(e != null){
            systemScheduledLogDO.setJobMessage(e.getClass().getName() + ": " + e.getMessage());
            systemScheduledLogDO.setStatus(ScheduleConstants.FAIL);
        }else{
            LocalDateTime end = LocalDateTime.now();
            Duration duration = Duration.between(start, end);
            String msg = systemScheduledDO.getJobName() + "耗时" + duration.toSeconds() + "秒";
            log.info(msg);
            systemScheduledLogDO.setJobMessage(msg);
            systemScheduledLogDO.setStatus(ScheduleConstants.SUCCESS);
        }
        SpringUtils.getBean(SystemScheduledLogService.class).save(systemScheduledLogDO);
    }

    /**
     * 任务执行方法
     * @param jobExecutionContext
     * @param systemScheduledDO
     * @throws Exception
     */
    abstract void doExecute(JobExecutionContext jobExecutionContext, SystemScheduledDO systemScheduledDO) throws Exception;
}
